package com.etooling.pdm.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.etooling.framework.entity.AttachFile;
import com.etooling.framework.entity.Employee;
import com.etooling.framework.entity.ImportDataBatch;
import com.etooling.framework.jpa.JpaQueryBuilder;
import com.etooling.framework.jpa.Specifications;
import com.etooling.framework.repository.EmployeeRepository;
import com.etooling.framework.repository.ImportDataBatchRepository;
import com.etooling.framework.svo.ReplyObj;
import com.etooling.framework.utils.EasyExcelEventListener;
import com.etooling.framework.utils.WebUtils;
import com.etooling.pdm.entity.Bom;
import com.etooling.pdm.entity.BomDetail;
import com.etooling.pdm.entity.GoodsSpecs;
import com.etooling.pdm.repository.BomDetailRepository;
import com.etooling.pdm.repository.BomRepository;
import com.etooling.pdm.repository.GoodsRepository;
import com.etooling.pdm.repository.GoodsSpecsRepository;
import com.etooling.pdm.service.BomService;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @author dan
 * @date 2024/1/17 17:14
 */
@Service
public class BomServiceImpl implements BomService {
    @Autowired
    EmployeeRepository employeeRepository;
    @Autowired
    BomRepository bomRepository;
    @Autowired
    BomDetailRepository bomDetailRepository;
    @Autowired
    GoodsSpecsRepository goodsSpecsRepository;
    @Autowired
    GoodsRepository goodsRepository;
    @Autowired
    ImportDataBatchRepository importDataBatchRepository;


    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public ReplyObj addBom(HttpServletRequest request, String json) {
        try {

            JSONObject jsonObject = JSON.parseObject(json);
            if (!WebUtils.checkStr(jsonObject)) {
                return WebUtils.flushFailure("解析数据时出现异常，没有BOM表数据");
            }
            String specsId = jsonObject.getString("specsId");
            if (!WebUtils.checkStr(specsId)) {
                return WebUtils.flushFailure("解析数据时出现异常，不知道为哪个产品创建的BOM表");
            }
            String bomName = jsonObject.getString("bomName");
            String memo = jsonObject.getString("memo");

            Bom bom = new Bom();
            GoodsSpecs goodsSpecs = new GoodsSpecs();
            goodsSpecs.setId(specsId);
            bom.setGoodsSpecs(goodsSpecs);
            String loginId = WebUtils.getSessionValue(request, WebUtils.LOGIN_USER_KEY);
            Employee one = employeeRepository.getOne(loginId);
            bom.setBomName(bomName);
            bom.setCreateUserName(one.getName());
            bom.setCreateUserId(loginId);
            bom.setCreateTime(new Date());
            bom.setMemo(memo);
            String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
            bom.setCompanyId(companyId);
            bom.setStatus(Bom.STATUS_RUN);
            bomRepository.save(bom);

            JSONArray jsonArray = jsonObject.getJSONArray("bomList");
            this.handleBomDetail(jsonArray, null, bom, companyId);

            return WebUtils.flushSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return WebUtils.flushFailure("解析数据时出现异常");
        }
    }


    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public ReplyObj updateBom(HttpServletRequest request, String json) {
        try {
            JSONObject jsonObject = JSON.parseObject(json);
            if (!WebUtils.checkStr(jsonObject)) {
                return WebUtils.flushFailure("解析数据时出现异常，没有BOM表数据");
            }
            String id = jsonObject.getString("id");
            if (!WebUtils.checkStr(id)) {
                return WebUtils.flushFailure("解析数据时出现异常，找不到修改的BOM表");
            }
            Bom bom = bomRepository.getById(id);
            String bomName = jsonObject.getString("bomName");
            String memo = jsonObject.getString("memo");
            bom.setBomName(bomName);
            bom.setMemo(memo);
            bom.setStatus(Bom.STATUS_RUN);
            bomRepository.save(bom);

            bomDetailRepository.deleteByBomId(bom.getId());

            String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
            JSONArray jsonArray = jsonObject.getJSONArray("bomList");
            this.handleBomDetail(jsonArray, null, bom, companyId);

            return WebUtils.flushSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return WebUtils.flushFailure("解析数据时出现异常");
        }
    }


    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)
    public ReplyObj delBom(HttpServletRequest request, String bomId) {
        try {
            Bom bom = bomRepository.getById(bomId);
            if (bom == null) {
                return WebUtils.flushFailure("找不到对应的Bom记录，删除失败");
            }
            bomDetailRepository.deleteByBomId(bomId);
            bomRepository.deleteById(bomId);
            return WebUtils.flushSuccess("删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return WebUtils.flushFailure("删除Bom失败：");
        }
    }

    /**
     * 根据url地址返回 读取流
     *
     * @param url
     * @return
     * @throws IOException
     */
    public static InputStream downloadExcel(String url) throws IOException {
        HttpClient httpClient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        HttpResponse response = httpClient.execute(httpGet);

        return response.getEntity().getContent();
    }


    @Override
    public void uploadBomExcel(ImportDataBatch importDataBatch, String loginId, String companyId, String bomName, String bomMemo) {
        InputStream inputStream = null;
        try {
            AttachFile attachFile = importDataBatch.getAttachFile();
            String webPath = attachFile.getWebPath();
            Employee employee = new Employee();
            employee.setId(loginId);

            // 流处理打开当时打开的文件
            inputStream = downloadExcel(webPath);

            // 创建 DynamicAnalysisEventListener 实例, 进行读取Excel内容
            EasyExcelEventListener listener = new EasyExcelEventListener();

            // 读取 Excel 文件并处理数据 // headRowNumber 标题行占几行，默认1行
            EasyExcel.read(inputStream, listener).sheet().headRowNumber(0).doRead();

            // 获取处理后的数据
            List<Map<Integer, String>> dataList = listener.getDataList();

            // 空文件拒绝
            if (dataList.size() == 0) {
                importDataBatch.setDoneTime(new Date());
                importDataBatch.setErrorMemo("提交的文件是空的或者格式不正确无法解析获取内容");
                importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
                importDataBatchRepository.save(importDataBatch);
                return;
            }
            // 只有标题拒绝
            if (dataList.size() == 1) {
                importDataBatch.setDoneTime(new Date());
                importDataBatch.setErrorMemo("提交的文件只有第一行标题，没有其他数据。或者格式不正确无法解析获取内容");
                importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
                importDataBatchRepository.save(importDataBatch);
                return;
            }


            // 解析第一行的标题内容
            Map<Integer, String> titleMap = dataList.get(0);
            // 反转获得标题在Excel表中的列序号
            Map<String, Integer> reversedMap = new HashMap<>();
            for (Map.Entry<Integer, String> entry : titleMap.entrySet()) {
                reversedMap.put(entry.getValue(), entry.getKey());
            }
            // 作为 产品数据导入 ，必须要有的列数据内容
            List<String> canNotNullTitleList = new ArrayList<>();
            canNotNullTitleList.add("物料层级");
            canNotNullTitleList.add("规格编码");
            canNotNullTitleList.add("单位");
            canNotNullTitleList.add("数量");
            canNotNullTitleList.add("产品角色");
            Set<String> strings = reversedMap.keySet();
            // 检查 canNotNullTitleList 中的所有元素是否都在 strings 中
            boolean containsAll = strings.containsAll(canNotNullTitleList);
            if (!containsAll) {
                // 找出缺少的元素并输出
                StringBuilder stringBuilder = new StringBuilder();
                for (String element : canNotNullTitleList) {
                    if (!strings.contains(element)) {
                        stringBuilder.append(element);
                        stringBuilder.append(";");
                    }
                }
                importDataBatch.setDoneTime(new Date());
                importDataBatch.setErrorMemo("导入的文件数据缺失，导入产品数据必须包括的内容：物料层级，规格编码，单位，数量，产品角色；当前导入的文件缺少：" + stringBuilder.toString());
                importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
                importDataBatchRepository.save(importDataBatch);
                return;
            }

            // 获取对应标题的的列序号, 没有这个标题的序号就是-1, 在数据列表里面的内容 -1 序号的是没有值的
            Integer levelIndex = reversedMap.containsKey("物料层级") ? reversedMap.get("物料层级") : -1;
            Integer skuCodeIndex = reversedMap.containsKey("规格编码") ? reversedMap.get("规格编码") : -1;
            Integer unitIndex = reversedMap.containsKey("单位") ? reversedMap.get("单位") : -1;
            Integer numIndex = reversedMap.containsKey("数量") ? reversedMap.get("数量") : -1;
            Integer roleIndex = reversedMap.containsKey("产品角色") ? reversedMap.get("产品角色") : -1;
            Integer memoIndex = reversedMap.containsKey("备注信息") ? reversedMap.get("备注信息") : -1;


            // 大于等于0的整数
            Pattern pattern1 = Pattern.compile("^\\d+$");
            // 数字
            Pattern pattern2 = Pattern.compile("-?\\d+(\\.\\d+)?");

            // 记录所有skuCode
            Map<String, Integer> skuCodeIndexMap = new HashMap<>();
            // 错误结果map
            Map<Integer, StringBuilder> failResultMap = new TreeMap<>();

            Map<Integer, String> firstRow = dataList.get(1);
            if (!firstRow.containsKey(levelIndex) || !"0".equals(firstRow.get(levelIndex))) {
                importDataBatch.setDoneTime(new Date());
                importDataBatch.setErrorMemo("不是从物料层级0开始，Bom表结构不合理");
                importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
                importDataBatchRepository.save(importDataBatch);
                return;
            }


            boolean haveZeroLevel = false;
            int rowLevel = 0;
            // 循环处理数据, 从第二行开始, 第一行时标题
            for (int i = 1; i < dataList.size(); i++) {
                Map<Integer, String> map = dataList.get(i);
                // 获取对应标题的所有内容
                String level = map.get(levelIndex);
                String skuCode = map.get(skuCodeIndex);
                String unit = map.get(unitIndex);
                String num = map.get(numIndex);
                String role = map.get(roleIndex);

                StringBuilder sb;
                if (!failResultMap.containsKey(i)) {
                    sb = new StringBuilder();
                } else {
                    sb = failResultMap.get(i);
                }

                if (!WebUtils.checkStr(level)) {
                    sb.append("物料层级是空的").append("\n");
                } else {
                    if (!pattern1.matcher(level).matches()) {
                        sb.append("物料层级不是大于等于0的整数").append("\n");
                    }
                }

                int levelInt = Integer.parseInt(level);
                if (levelInt == 0) {
                    if (!haveZeroLevel) {
                        haveZeroLevel = true;
                    } else {
                        sb.append("已经有了物料层级0").append("\n");
                    }
                }
                // 层级的跳动超过2，例如，水管304是层级2，那么它的下属Bom表应该是层级3，但是结果是层级4，那就是错的
                if ((levelInt - rowLevel) >= 2) {
                    sb.append("层级有问题，和上一行的层级跨动超过1").append("\n");
                } else {
                    rowLevel = levelInt;
                }

                if (!WebUtils.checkStr(skuCode)) {
                    sb.append("规格编码是空的").append("\n");
                } else {
                    skuCodeIndexMap.put(skuCode, i);
                }
                if (!WebUtils.checkStr(unit)) {
                    sb.append("单位是空的").append("\n");
                }
                if (!WebUtils.checkStr(num)) {
                    sb.append("数量是空的").append("\n");
                } else {
                    if (!pattern2.matcher(num).matches()) {
                        sb.append("数量不是数字").append("\n");
                    }
                }
                if (!WebUtils.checkStr(role)) {
                    sb.append("产品角色是空的").append("\n");
                }

                if (sb.length() != 0) {
                    failResultMap.put(i, sb);
                }
            }

            // 所有的skuCode
            List<String> skuCodeList = new ArrayList<>(skuCodeIndexMap.keySet());
            // 哪些skuCode是存在的
            List<String> existSkuCodeList = goodsSpecsRepository.skuCodeExistList(skuCodeList, companyId, GoodsSpecs.STATUS_RUNNING);
            // 排除出来不存在的skuCode
            List<String> notExistInList = new ArrayList<>(skuCodeList);
            notExistInList.removeAll(existSkuCodeList);

            // 检查的时候发现了错误内容
            if (!failResultMap.isEmpty() || !notExistInList.isEmpty()) {
                StringBuilder stringBuilder = new StringBuilder();

                for (String s : notExistInList) {
                    Integer index = skuCodeIndexMap.get(s);
                    StringBuilder sb;
                    if (!failResultMap.containsKey(index)) {
                        sb = new StringBuilder();
                    } else {
                        sb = failResultMap.get(index);
                    }
                    sb.append("规格编码{ ").append(s).append(" }不存在;\n");
                    failResultMap.put(index, sb);
                }

                for (Map.Entry<Integer, StringBuilder> entry : failResultMap.entrySet()) {
                    stringBuilder.append("第").append(entry.getKey() + 1).append("行\n").append(entry.getValue());
                }

                importDataBatch.setDoneTime(new Date());
                importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
                importDataBatch.setErrorMemo(stringBuilder.toString());
                importDataBatchRepository.save(importDataBatch);
                return;
            }


            // 处理内容成BOM结构
            List<Map<String, Object>> bomList = new ArrayList<>();
            for (int i = 1; i < dataList.size(); i++) {
                Map<Integer, String> map = dataList.get(i);
                // 获取对应标题的所有内容
                String level = map.get(levelIndex);
                String skuCode = map.get(skuCodeIndex);
                String unit = map.get(unitIndex);
                String num = map.get(numIndex);
                String role = map.get(roleIndex);
                String memo = map.get(memoIndex);

                int nowLevel = Integer.parseInt(level);
                // 当前的bomList
                List<Map<String, Object>> nowBomList = bomList;
                for (int j = 0; j < nowLevel; j++) {
                    Map<String, Object> nowMap = nowBomList.get(nowBomList.size() - 1);
                    nowBomList = (List<Map<String, Object>>) nowMap.get("children");
                }
                if (nowBomList == null) {
                    nowBomList = new ArrayList<>();
                }

                Map<String, Object> nowMap = new HashMap<>();
                nowMap.put("level", level);
                nowMap.put("skuCode", skuCode);
                nowMap.put("unit", unit);
                nowMap.put("num", num);
                nowMap.put("role", role);
                nowMap.put("memo", memo);
                List<Map<String, Object>> childrenList = new ArrayList<>();
                nowMap.put("children", childrenList);

                nowBomList.add(nowMap);
            }


            JpaQueryBuilder pb = Specifications.<GoodsSpecs>and();
            pb.eq("companyId", companyId);
            pb.in("skuCode", skuCodeList);
            List<GoodsSpecs> goodsSpecsList = goodsSpecsRepository.findAll(pb.build());
            Map<String, GoodsSpecs> goodsSpecsSkuCodeMap = new HashMap<>();
            for (GoodsSpecs goodsSpecs : goodsSpecsList) {
                goodsSpecsSkuCodeMap.put(goodsSpecs.getSkuCode(), goodsSpecs);
            }

            // 保存BOM表表头
            Map<String, Object> map = bomList.get(0);
            String skuCode = (String) map.get("skuCode");

            GoodsSpecs goodsSpecs = goodsSpecsSkuCodeMap.get(skuCode);

            Bom bom = new Bom();
            bom.setGoodsSpecs(goodsSpecs);
            Employee uploadUser = importDataBatch.getUploadUser();
            bom.setBomName(bomName);
            bom.setCreateUserName(uploadUser.getName());
            bom.setCreateUserId(loginId);
            bom.setCreateTime(new Date());
            bom.setMemo(bomMemo);
            bom.setCompanyId(companyId);
            bom.setStatus(Bom.STATUS_RUN);
            bom.setBatchId(importDataBatch.getId());
            bomRepository.save(bom);

            saveBomDetailList(bom, bomList, null, goodsSpecsSkuCodeMap);


            importDataBatch.setDoneTime(new Date());
            importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
            importDataBatch.setErrorMemo("不正确的访问，不是导入物料也不是导入价格，不确认的访问类别");
            importDataBatchRepository.save(importDataBatch);

        } catch (Exception e) {
            e.printStackTrace();
            // 获取异常类型
            String exceptionType = e.getClass().getSimpleName();
            // 获取异常消息
            String exceptionMessage = e.getMessage();
            // 获取异常的位置（代码行号）
            StackTraceElement[] stackTrace = e.getStackTrace();
            String exceptionLocation = "";
            if (stackTrace.length > 0) {
                StackTraceElement firstStackTraceElement = stackTrace[0];
                exceptionLocation = firstStackTraceElement.getClassName() + "." + firstStackTraceElement.getMethodName() + "(" + firstStackTraceElement.getFileName() + ":" + firstStackTraceElement.getLineNumber() + ")";
            }

            // 组合成字符串
            String exceptionDetails = "异常类型: " + exceptionType + "\n" + "异常发生位置: " + exceptionLocation + "\n" + "异常内容: " + exceptionMessage;

            // 打印异常信息字符串
            System.out.println(exceptionDetails);
            // 修改上传文件记录
            importDataBatch.setDoneTime(new Date());
            importDataBatch.setErrorMemo("提交过程中发生异常，请联系管理员进行处理");
            importDataBatch.setStatus(ImportDataBatch.STATUS_SUBMIT_FAILE);
            importDataBatchRepository.save(importDataBatch);

        } finally {
            try {
                // 关闭流
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    @Override
    @Transactional
    public ReplyObj updateBomDetails(HttpServletRequest request, String materialGoodsSpecsId, String recordDetailId) {
        try {
            BomDetail bomDetail = bomDetailRepository.getById(recordDetailId);
            GoodsSpecs goodsSpecs = goodsSpecsRepository.getById(materialGoodsSpecsId);
            //规格编码
            String skuCode = goodsSpecs.getSkuCode();
//            //规格名称
//            String specsNames = goodsSpecs.getSpecsNames();
//            Goods goods = goodsRepository.getById(goodsSpecs.getGoods().getId());
//            //型号名称
//            String goodsNamesPath = goods.getGoodsNamesPath();
//            //型号编码
//            String materialCode = goods.getMaterialCode();
//            bomDetail.setMaterialGoodsCode(materialCode);
//            bomDetail.setMaterialGoodsName(goodsNamesPath);
//            bomDetail.setMaterialSpecsName(specsNames);
            bomDetail.setSkuCode(skuCode);
            bomDetail.setGoodsSpecsId(goodsSpecs.getId());
            bomDetailRepository.save(bomDetail);

        } catch (Exception e) {
            return WebUtils.flushFailure();
        }
        return WebUtils.flushSuccess();
    }


    /**
     * 启用Bom
     *
     * @param request
     * @param specsId
     * @param bomId
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.SERIALIZABLE, rollbackFor = Exception.class)
    public ReplyObj enableBom(HttpServletRequest request, String specsId, String bomId) {
        bomRepository.updateEnableBom(bomId, specsId, Bom.STATUS_RUN, Bom.STATUS_DISABLE);
        return WebUtils.flushSuccess();
    }


    /**
     * 添加BomDetail的下层物料列表
     *
     * @param request
     * @param parentBomDetailId
     * @param goodsSpecsIds
     * @return
     */
    @Override
    public ReplyObj addBomDetail(HttpServletRequest request, String parentBomDetailId, List<String> goodsSpecsIds) {
        // 拿到最大的seq
        Integer maxSeq = bomDetailRepository.getMaxSeq(parentBomDetailId);
        if (maxSeq == null) {
            maxSeq = 0;
        }
        // 拿到父类bomDetail
        BomDetail parentBomDetail = bomDetailRepository.getById(parentBomDetailId);
        int level = 0;
        if (parentBomDetail.getLevel() != null) {
            level = parentBomDetail.getLevel() + 1;
        }
        // 拿到所有的规格数据
        List<GoodsSpecs> addSpecsList = goodsSpecsRepository.findAll(Specifications.<GoodsSpecs>and().in("id", goodsSpecsIds).build());

        String companyId = WebUtils.getSessionValue(request, WebUtils.LOGIN_COMPANY_ID_KEY);
        List<BomDetail> addBomDetailList = new ArrayList<>();

        for (GoodsSpecs goodsSpecs : addSpecsList) {
            BomDetail bomDetail = new BomDetail();
            bomDetail.setBom(parentBomDetail.getBom());
            bomDetail.setLevel(level);
            bomDetail.setSeq(++maxSeq);
            bomDetail.setGoodsSpecsId(goodsSpecs.getId());
            bomDetail.setMaterialSpecsName(goodsSpecs.getSpecsNames());
            bomDetail.setMaterialSpecsCode(goodsSpecs.getSkuCode());
            bomDetail.setMaterialGoodsName(goodsSpecs.getGoods().getName());
            bomDetail.setMaterialGoodsCode(goodsSpecs.getGoods().getMaterialCode());
            bomDetail.setSkuCode(goodsSpecs.getSkuCode());
            bomDetail.setUnit(goodsSpecs.getGoods().getUnit());
            bomDetail.setUnitNum(1d);
            bomDetail.setMaterialTag("自制件");
            bomDetail.setCompanyId(companyId);
            bomDetail.setParentId(parentBomDetailId);
            addBomDetailList.add(bomDetail);
        }

        bomDetailRepository.saveAll(addBomDetailList);

        return WebUtils.flushSuccess();
    }


    /**
     * @param bom                  bom对象
     * @param bomList              bom列表结构
     * @param goodsSpecsSkuCodeMap 键值对是skuCode和规格对象
     */
    private void saveBomDetailList(Bom bom, List<Map<String, Object>> bomList, String parentId, Map<String, GoodsSpecs> goodsSpecsSkuCodeMap) {
        for (int i = 0; i < bomList.size(); i++) {
            Map<String, Object> map = bomList.get(i);
            Integer level = Integer.parseInt(String.valueOf(map.get("level")));
            String skuCode = (String) map.get("skuCode");
            String unit = (String) map.get("unit");
            Double num = Double.parseDouble(String.valueOf(map.get("num")));
            String role = (String) map.get("role");
            String memo = (String) map.get("memo");
            List<Map<String, Object>> children = (List<Map<String, Object>>) map.get("children");

            GoodsSpecs goodsSpecs = goodsSpecsSkuCodeMap.get(skuCode);

            BomDetail bomDetail = new BomDetail();
            bomDetail.setBom(bom);
            bomDetail.setLevel(level);
            bomDetail.setSeq(i);
            bomDetail.setGoodsSpecsId(goodsSpecs.getId());
            bomDetail.setMaterialSpecsName(goodsSpecs.getSpecsNames());
            bomDetail.setMaterialSpecsCode(goodsSpecs.getSkuCode());
            bomDetail.setMaterialGoodsName(goodsSpecs.getGoods().getName());
            bomDetail.setMaterialGoodsCode(goodsSpecs.getGoods().getMaterialCode());
            bomDetail.setUnit(unit);
            bomDetail.setUnitNum(num);
            bomDetail.setMaterialTag(role);
            bomDetail.setMemo(memo);
            bomDetail.setCompanyId(bom.getCompanyId());
            bomDetail.setParentId(parentId);
            bomDetailRepository.save(bomDetail);
            if (!children.isEmpty()) {
                saveBomDetailList(bom, children, bomDetail.getId(), goodsSpecsSkuCodeMap);
            }
        }

    }


    private void handleBomDetail(JSONArray jsonArray, BomDetail parentBomDetail, Bom bom, String companyId) {
        for (int i = 0; i < jsonArray.size(); i++) {
            String jsonString = jsonArray.getString(i);
            JSONObject detailJson = JSON.parseObject(jsonString);

            BomDetail bomDetail = new BomDetail();
            if (parentBomDetail != null) {
                bomDetail.setParentId(parentBomDetail.getId());
            }
            bomDetail.setBom(bom);
            bomDetail.setLevel(detailJson.getInteger("level"));
            bomDetail.setSeq(i);
            bomDetail.setGoodsSpecsId(detailJson.getString("specsId"));
            bomDetail.setMaterialSpecsName(detailJson.getString("materialSpecsName"));
            bomDetail.setMaterialSpecsCode(detailJson.getString("materialSpecsCode"));
            bomDetail.setMaterialGoodsName(detailJson.getString("materialGoodsName"));
            bomDetail.setMaterialGoodsCode(detailJson.getString("materialGoodsCode"));
            bomDetail.setUnit(detailJson.getString("unit"));
            bomDetail.setUnitNum(detailJson.getDouble("unitNum"));
            bomDetail.setMaterialTag(detailJson.getString("materialTag"));
            bomDetail.setMemo(detailJson.getString("memo"));
            bomDetail.setCompanyId(companyId);
            bomDetailRepository.save(bomDetail);
            JSONArray children = detailJson.getJSONArray("children");
            if (children != null) {
                this.handleBomDetail(children, bomDetail, bom, companyId);
            }
        }

    }


}
